/// 1. 在此节之前讨论过的都是安全的Rust,即Rust在编译时会强制执行的内存安全保证。不会强制执行这类美内存安全 保证的,就是不安全的Rust。
/// 2. 不安全的Rust存在的两大原因:
/// - 静态分析本质上是保守的,就意味着某些代码可能能是合法的,但是Rust也会拒绝。在此情况下,可以使用不安全的代码。
/// - 底层计算机硬件固有的不安全性。如果Rust不允许进行不安全的操作,有些任务根本就完成不了。
/// 3. 不安全的Rust具有的超级力量
/// Rust会通过unsafe关键字切换到不安全的Rust。不安全的Rust具有以下超级力量:
/// - 解引用裸指针
/// - 调用不安全的函数或者方法
/// - 访问或修改可变静态变量
/// - 实现不安全的trait
/// ###### 注意:unsafe并不会关闭借用检查器或禁用任何其它的Rust安全检查规则,它只提供上述几个不被编译器检查内存安
/// ###### 全的功能。unsafe也不意味着块中的代码一定就是不ok的,它只是表示由程序员来确保安全。
///

// 解引用裸指针：
// 分为可变和不可变，分别写作"*counts T", "*mut T"
// 1. 允许忽略借用规则，可以同时拥有不可变和可变指针，或者是多个指向相同位置的可变指针
// 2. 不保证指向的内存是有效的
// 3. 允许为空
// 4. 不能实现任何自动清理的功能
fn main() {
    let mut num = 5;
    // 创建一个不可变的裸指针，可以在安全的代码中，只是不能在不安全代码快之外解引用裸指针
    let r1 = &num as *const i32;
    // 创建一个可变的裸指针，可以在安全的代码中，只是不能在不安全代码快之外解引用裸指针
    let r2 = &mut num as *mut i32;

    // 如下解引用报错“dereference of raw pointer”
    // println!("r1 = {}", *r1);
    // println!("r2 = {}", *r2);

    // 要解引用必须加上unsafe关键字
    unsafe {
        println!("r1 is: {}", *r1);
        println!("r2 is: {}", *r2);
    }

    // 一个内存地址无效的裸指针
    let mut add = 0x12345usize;
    let r = add as *const i32;
    let s = add as *mut i32;
    println!("Hello, world!");
}
